/*
Copyright 2008  Four Roads LLC conact@4-roads.com

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either 
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
using System.Web;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;


using CommunityServer.Configuration;
using CommunityServer.Components;


namespace FourRoads.Links
{
	[Flags(),
	Serializable()]
	public enum ResLinkPermissionEnum : long 
	{
		ViewLink		= 0x0000000000000001,
		AddLinks		= 0x0000000000000002,
		RemoveLinks		= 0x0000000000000004,
		Moderate		= 0x0000000000000008,
		EditLinks		= 0x0000000000000040,
		ReportDeadLinks	= 0x0000000000000080,
		AddComments		= 0x0000000000000100
	}

	public class ExtendedUserRoles
	{
		static RolesConfiguration roles = CSConfiguration.GetConfig().RolesConfiguration;

		protected static bool IsInRoles( string[] roleNames  , string userName) 
		{
			string [] userRoles = Roles.GetUserRoleNames( userName );
			foreach( string userRole in userRoles ) 
			{
				foreach( string roleName in roleNames ) 
				{
					if( roleName == userRole )
						return true;
				}
			}
			return false;
		}

		public static bool IsLinkAdministrator
		{
			get
			{
				return _IsLinkAdministrator(CSContext.Current.User.Username);
			}
		}

		///	<summary>
		///	Specifies if a user	in an administrator	or not.
		///	</summary>
		public static bool _IsLinkAdministrator(string userName)
		{
			try	
			{
				return IsInRoles( new string[] { roles.SystemAdministrator,  "Link Administrator"}  , userName);
			}
			catch(Exception ex)
			{
				new CSException(CSExceptionType.UnknownError , "IsLinkAdministrator" , ex).Log();
			}

			return false;			 
		}

	}

	/// <summary>
	/// Summary description for ResLinkPermission.
	/// </summary>
	[Serializable()]
	public class ResLinkPermission : PermissionBase 
	{
		public ResLinkPermission() : base() 
		{
		}
		public ResLinkPermission(  int site, Guid role, string name, Permission allow, Permission deny, bool impliedPermissions ) 
			: base( site, role, name, allow, deny, impliedPermissions ) 
		{
		}


		#region Public Properites - Permissions
		public virtual bool ViewLink 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.ViewLink ); }
		}

		public virtual bool AddLinks 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.AddLinks  ); }
		}

		public virtual bool EditLinks 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.EditLinks); }
		}

		public virtual bool ReportDeadLinks 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.ReportDeadLinks); }
		}

		public virtual bool RemoveLinks 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.RemoveLinks ); }
		}

		public virtual bool Moderate 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.Moderate ); }
		}

		public virtual bool AddComments 
		{
			get{ return GetBit( (Permission)ResLinkPermissionEnum.AddComments ); }
		}
		#endregion


		public static bool Validate(Section section, Permission permission, User user, Post p) 
		{
			return Validate(section , (ResLinkPermissionEnum)permission ,  user , p);
		}

		public static bool Validate(Section section, ResLinkPermissionEnum permission, User user, Post p) 
		{
			if(section == null || section.PermissionSet == null || user == null )
				return false;

			ExtendedUserRoles rolesCheck = new ExtendedUserRoles();

			if(ExtendedUserRoles.IsLinkAdministrator)
				return true;

			bool bReturn = true;
			ResLinkPermission fpFinal = section.ResolvePermission(user) as ResLinkPermission;

			if((permission == (permission | ResLinkPermissionEnum.AddLinks)) && bReturn )
				bReturn &= fpFinal.AddLinks;

			if((permission == (permission | ResLinkPermissionEnum.Moderate)) && bReturn )
				bReturn &= fpFinal.Moderate;

			if((permission == (permission | ResLinkPermissionEnum.RemoveLinks)) && bReturn )
				bReturn &= fpFinal.RemoveLinks;

			if((permission == (permission | ResLinkPermissionEnum.ViewLink)) && bReturn )
				bReturn &= fpFinal.ViewLink;
		
			if((permission == (permission | ResLinkPermissionEnum.EditLinks)) && bReturn )
				bReturn &= fpFinal.EditLinks;
			
			if((permission == (permission | ResLinkPermissionEnum.ReportDeadLinks)) && bReturn )
				bReturn &= fpFinal.ReportDeadLinks;
			
			if((permission == (permission | ResLinkPermissionEnum.AddComments)) && bReturn )
				bReturn &= fpFinal.AddComments;

			return bReturn;
		}

		#region AccessCheck

		public static bool LightAccessCheck(ResLinkSection section , Permission permission ,  User user)
		{
			return LightAccessCheck(section , (ResLinkPermissionEnum)permission ,  user);
		}

		public static bool LightAccessCheck(ResLinkSection section , ResLinkPermissionEnum permission ,  User user)
		{
			CSContext csContext = CSContext.Current;

			//TODO: Access check for Resource Links
			if(ExtendedUserRoles.IsLinkAdministrator)
				return true;

			ResLinkPermission fp = section.ResolvePermission( user ) as ResLinkPermission;

			long lValue = (long)permission;
			switch (lValue) 
			{
				case (long)ResLinkPermissionEnum.ViewLink:
					if (!fp.ViewLink)
						return false;
					break;

				case (long)ResLinkPermissionEnum.RemoveLinks:
					if (!fp.RemoveLinks)
						return false;
					break;

				case (long)ResLinkPermissionEnum.Moderate:
					if (!fp.Moderate && !csContext.User.IsModerator)
						return false;
					break;

				case (long)ResLinkPermissionEnum.AddLinks:
					if (!fp.AddLinks)
						return false;
					break;
				case (long)ResLinkPermissionEnum.EditLinks:
					if (!fp.EditLinks)
						return false;
					break;
				case (long)ResLinkPermissionEnum.ReportDeadLinks:
					if (!fp.ReportDeadLinks)
						return false;
					break;
				case (long)ResLinkPermissionEnum.AddComments:
					if (!fp.AddComments)
						return false;
					break;
			}

			return true;
		}

		public static void AccessCheck(Section section, Permission permission, User user, Post post) 
		{
			AccessCheck(section , (ResLinkPermissionEnum)permission ,  user);
		}

		public static void AccessCheck(Section section, ResLinkPermissionEnum permission, User user) 
		{
	
			CSContext csContext = CSContext.Current;

			//TODO: Access check for Resource Links
			if(ExtendedUserRoles.IsLinkAdministrator)
				return;

			ResLinkPermission fp = section.ResolvePermission( user ) as ResLinkPermission;

			long lValue = (long)permission;
			switch (lValue) 
			{
				case (long)ResLinkPermissionEnum.ViewLink:
					if (!fp.ViewLink)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.ViewLinkAccessDenied);
					break;

				case (long)ResLinkPermissionEnum.RemoveLinks:
					if (!fp.RemoveLinks)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.RemoveLinksAccessDenied);
					break;

				case (long)ResLinkPermissionEnum.Moderate:
					if (!fp.Moderate && !csContext.User.IsModerator)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.ModerateAccessDenied);
					break;

				case (long)ResLinkPermissionEnum.AddLinks:
					if (!fp.AddLinks)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.AddLinksAccessDenied);
					break;

				case (long)ResLinkPermissionEnum.EditLinks:
					if (!fp.EditLinks)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.EditLinksAccessDenied);
					break;

				case (long)ResLinkPermissionEnum.ReportDeadLinks:
					if (!fp.ReportDeadLinks)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.ReportDeadLinksAccessDenied);
					break;			

				case (long)ResLinkPermissionEnum.AddComments:
					if (!fp.AddComments)
						RedirectOrExcpetion((CSExceptionType)RlMessageTypes.AddLinkCommentsAccessDenied);
					break;	
			}
		}
		#endregion

	}
}
